#include"ttfParserSetting.hpp"
#include"ttfParser_Cell_TableCovers.hpp"
#include<glm/vec2.hpp>
#ifdef USE_LCCTOOLBOX_AS_DLL
#	define LCCTOOLBOX_DLL_IMPORT_LCCTOOLBOX
#	ifdef _WIN32
#		pragma comment(lib,"lcctoolbox")
#	endif
#endif
#include<lcctoolbox_block.hpp>
#include<lcctoolbox_markset.hpp>// for ttfReader


template<class T>
T& endianSwap(T& obj){
	union{T copy;unsigned char unit[sizeof(T)];};
	copy=obj;
	unsigned char*byte=(unsigned char*)(&obj);
	for(size_t i=0;i<sizeof(T)/2;++i)
	{	byte[sizeof(T)-1-i]=unit[i];
		byte[i]=unit[sizeof(T)-1-i];
	}
	return obj;
}



namespace LccStuffCollector{
namespace TTFParser{




class ttfReader;

struct theBase{
	// common func
	virtual void form()=0;
	virtual void print(){};
	// state chg func
	void allowForm(){formPass=true;};
	ttfReader* center;
	bool formPass=true;
	bool formed=false;
};



// done
struct fileHead:public theBase{
	uint8_t* scaler_type;
	uint16_t* numTables;
	uint16_t* searchRange;
	uint16_t* entrySelector;
	uint16_t* rangeShift;
	TTFPARSER_API void form();
	TTFPARSER_API void print();
	fileHeadCover* cover=nullptr;
	friend class tableItem;
};




// done
struct tableItem:public theBase{
	uint8_t* tag;
	uint32_t* checkSum;
	uint32_t* offset;
	uint32_t* length;
	TTFPARSER_API void form();
	TTFPARSER_API void print();
	tableItemCover* cover=nullptr;
};




// done
// name post head maxp cmap loca glyf hhea hmtx
struct nameTable:public theBase{
	uint16_t* format;
	uint16_t* count;
	uint16_t* stringOffset;
	nameTableCover::NameRecord* nameRecord;// array
	void* name;// line
	TTFPARSER_API void form();
	TTFPARSER_API void print();
	nameTableCover* cover=nullptr;
};




// struct postTable{};// now needn't




// wait test
struct headTable:public theBase{
	Fixed* version;
	Fixed* fontRevision;
	uint32_t* checkSumAdjustment;
	uint32_t* magicNumber;
	uint16_t* flags;// flag
	uint16_t* unitsPerEm;
	longDateTime* created;
	longDateTime* modified;
	FWord* xMin;
	FWord* yMin;
	FWord* xMax;
	FWord* yMax;
	uint16_t* macStyle;// flag
	uint16_t* lowestRecPPEM;
	int16_t* fontDirectionHint;// flag
	int16_t* indexToLocFormat;// 'loca' need
	int16_t* glyphDataFormat;
	TTFPARSER_API void form();
	TTFPARSER_API void print();
	headTableCover* cover=nullptr;
};




// wait test
struct maxpTable:public theBase{
	Fixed* version;
	uint16_t* numGlyphs;
	uint16_t* maxPoints;
	uint16_t* maxContours;
	uint16_t* maxComponentPoints;
	uint16_t* maxComponentContours;
	uint16_t* maxZones;
	uint16_t* maxTwilightPoints;
	uint16_t* maxStorage;
	uint16_t* maxFunctionDefs;
	uint16_t* maxInstructionDefs;
	uint16_t* maxStackElements;
	uint16_t* maxSizeOfInstructions;
	uint16_t* maxComponentElements;
	uint16_t* maxComponentDepth;
	TTFPARSER_API void form();
	TTFPARSER_API void print();
	maxpTableCover* cover=nullptr;
};




struct cmapSubTable:public theBase{
	uint16_t* format;
	uint16_t* length;
	uint16_t* language;
	struct format0{};
	struct format2{
		uint16_t* subHeaderKeys;// array
		cmapSubTableCover::format2::subHeader* subHeaders;// array
	};
	struct format4{
		uint16_t* segCountX2;
		uint16_t* searchRange;
		uint16_t* entrySelector;
		uint16_t* rangeShift;
		uint16_t* endCode;// array
		uint16_t* reservedPad;
		uint16_t* startCode;// array
		int16_t* idDelta;// array
		uint16_t* idRangeOffset;// array
		uint16_t* glyphIndexArray;// array
	};
	struct format6{};
	struct format8{};
	struct format10{};
	struct format12{};
	struct format13{};
	struct format14{};
	union{format0 f0;
	      format2 f2;
	      format4 f4;
	      format6 f6;
	      format8 f8;
	      format10 f10;
	      format12 f12;
	      format13 f13;
	      format14 f14;
	  };
	TTFPARSER_API void form();
	// TTFPARSER_API void print();
	cmapSubTableCover* cover=nullptr;
};

// done main, format yet not
struct cmapTable:public theBase{
	uint16_t* version;
	uint16_t* numberSubtables;
	cmapTableCover::SubTable* subTable;// array
	cmapSubTable theSubTable;
	// map rst
	TTFPARSER_API void form();
	TTFPARSER_API void print();
	cmapTableCover* cover=nullptr;
};





// done
// FILE STRUCTURE: T might be uint16 or uint32 which decide by 'head' table's indexToLocFormat item
// FILE STRUCTURE: The number of glyphs in a font must be stored in the Maximum Profile 'maxp' table.// The actual local offset (divided by 2 if is uint16) is stored. The value of n is the number of glyphs in the font + 1. The number of glyphs in the font is found in the maximum profile table.
struct locaTable:public theBase{
	union{uint16_t* offsets_16;uint32_t* offsets_32;void* offsets=nullptr;};// array
	TTFPARSER_API void form();
	// TTFPARSER_API void print();
	locaTableCover* cover=nullptr;
};




// done
// glyfItem
enum flag_simple{
	On_Curve      =1<<0,
			// If set, the point is on the curve;
			// Otherwise, it is off the curve.
	x_Short_Vector=1<<1,
			// If set, the corresponding x-coordinate is 1 byte long;
			// Otherwise, the corresponding x-coordinate is 2 bytes long
	y_Short_Vector=1<<2,
			// If set, the corresponding y-coordinate is 1 byte long;
			// Otherwise, the corresponding y-coordinate is 2 bytes long
	Repeat        =1<<3,
			// If set, the next byte specifies the number of additional times this set of flags is to be repeated. In this way, the number of flags listed can be smaller than the number of points in a character.
	This_x_is_same=1<<4,// (Positive x-Short vector)
			// This flag has one of two meanings, depending on how the x-Short Vector flag is set.
			// If the x-Short Vector bit is set, this bit describes the sign of the value, with a value of 1 equalling positive and a zero value negative.
			// If the x-short Vector bit is not set, and this bit is set, then the current x-coordinate is the same as the previous x-coordinate.
			// If the x-short Vector bit is not set, and this bit is not set, the current x-coordinate is a signed 16-bit delta vector. In this case, the delta vector is the change in x
	This_y_is_same=1<<5// (Positive y-Short vector)
			// This flag has one of two meanings, depending on how the y-Short Vector flag is set.
			// If the y-Short Vector bit is set, this bit describes the sign of the value, with a value of 1 equalling positive and a zero value negative.
			// If the y-short Vector bit is not set, and this bit is set, then the current y-coordinate is the same as the previous y-coordinate.
			// If the y-short Vector bit is not set, and this bit is not set, the current y-coordinate is a signed 16-bit delta vector. In this case, the delta vector is the change in y
	// Reserved 6 - 7 Set to zero
};
enum flag_component{
	ARG_1_AND_2_ARE_WORDS   =1<<0,
			// If set, the arguments are words;
			// If not set, they are bytes.
	ARGS_ARE_XY_VALUES      =1<<1,
			// If set, the arguments are xy values;
			// If not set, they are points.
	ROUND_XY_TO_GRID        =1<<2,
			// If set, round the xy values to grid;
			// if not set do not round xy values to grid (relevant only to bit 1 is set)
	WE_HAVE_A_SCALE         =1<<3,
			// If set, there is a simple scale for the component.
			// If not set, scale is 1.0.
	// (this bit is obsolete)	4// (obsolete; set to zero)
	MORE_COMPONENTS         =1<<5,
			// If set, at least one additional glyph follows this one.
	WE_HAVE_AN_X_AND_Y_SCALE=1<<6,
			// If set the x direction will use a different scale than the y direction.
	WE_HAVE_A_TWO_BY_TWO    =1<<7,
			// If set there is a 2-by-2 transformation that will be used to scale the component.
	WE_HAVE_INSTRUCTIONS    =1<<8,
			// If set, instructions for the component character follow the last component.
	USE_MY_METRICS          =1<<9,
			// Use metrics from this component for the compound glyph.
	OVERLAP_COMPOUND        =1<<10
			// If set, the components of this compound glyph overlap.
};
struct glyfItem:public theBase{
	int16_t* numberOfContours;
	FWord* xMin;
	FWord* yMin;
	FWord* xMax;
	FWord* yMax;
	struct simpleCase{
		uint16_t* endPtsOfContours;// array, lenth is numberOfContours
		uint16_t* instructionLength;
		uint8_t* instructions;// array, lenth is instructionLength
		// uint8_t* flags// array
		// union{uint8_t* xCoordinates_u8;int16_t* xCoordinates_16;};// array
		// union{uint8_t* yCoordinates_u8;int16_t* yCoordinates_16;};// array
		uint8_t* dataPacket;// cause flags influent coord's parse, we can't read coord separately
		typedef LccToolbox::block<glm::ivec2> points;
		typedef LccToolbox::block<uint8_t> flags;
		struct contour
		{	points _points;
			flags _flags;
		};
		LccToolbox::block<contour> contours;
	};
	struct componentCase{
		// uint16_t flags;// Component flag
		// uint16_t glyphIndex;// Glyph index of component
		// int16_t, uint16_t, int8_t or uint8_t argument1;// X-offset for component or point number; type depends on bits 0 and 1 in component flags
		// int16_t, uint16_t, int8_t or uint8_t argument2;// Y-offset for component or point number type depends on bits 0 and 1 in component flags
		// [follow union] transformation option;// One of the transformation options from Table 19
		uint8_t* dataPacket;// cause flags influent coord's parse, we can't read coord separately
		struct glyph
		{	uint16_t flag;
			uint16_t index;
			int32_t argument[2];
			LccToolbox::block<int16_t> scale;
		};
		LccToolbox::block<glyph> glyphs;
	};
	simpleCase simple;
	componentCase component;
	TTFPARSER_API void form();
	// TTFPARSER_API void print();
	glyfItemCover* cover=nullptr;
	bool is_simple;
};




// struct hheaTable{};
// struct hmtxTable{};



// name post head maxp cmap loca glyf hhea hmtx
#define Table(A) A##Table A
class ttfReader{
public:
	fileHead filehead;
	LccToolbox::block<tableItem> tableitems;
// private:
	LccToolbox::markSetAuto tableIndexs;
	LccToolbox::mark _name;
//	LccToolbox::mark _post;
	LccToolbox::mark _head;
	LccToolbox::mark _maxp;
	LccToolbox::mark _cmap;
	LccToolbox::mark _loca;
	LccToolbox::mark _glyf;
//	LccToolbox::mark _hhea;
//	LccToolbox::mark _hmtx;

public:
	Table(name);
//	Table(post);
	Table(head);
	Table(maxp);
	Table(cmap);
	Table(loca);// rely on maxp & head
//	block<glyfItem> glyfs;
//	Table(hhea);
//	Table(hmtx);

	TTFPARSER_API void formAt(void*);
	TTFPARSER_API void print();
};




}// namespace TTFParser
}// namespace LccStuffCollector